import logging
from typing import Optional
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database.mysql.usermodel import User

logger = logging.getLogger(__name__)

# 创建或获取用户
async def create_or_get_user(
    db: AsyncSession,
    user_id: str,
    initial_energy: int = 30
) -> User:
    """创建或获取用户，如果是新用户则初始化能量"""
    try:
        # 先尝试获取现有用户
        result = await db.execute(
            select(User).where(User.user_id == user_id).where(User.is_deleted == False)
        )
        user = result.scalar_one_or_none()
        
        if user:
            logger.info(f"获取到现有用户: {user_id}, 当前能量: {user.energy}")
            return user
        
        # 创建新用户
        new_user = User(
            user_id=user_id,
            energy=initial_energy
        )
        
        db.add(new_user)
        await db.flush()
        await db.refresh(new_user)
        

        
        logger.info(f"创建新用户: {user_id}, 初始化能量: {initial_energy}")
        return new_user
        
    except Exception as e:
        logger.error(f"创建或获取用户失败: {str(e)}", exc_info=True)
        raise e

# 获取用户信息
async def get_user_by_id(db: AsyncSession, user_id: str) -> Optional[User]:
    """根据用户ID获取用户信息"""
    try:
        result = await db.execute(
            select(User).where(User.user_id == user_id).where(User.is_deleted == False)
        )
        return result.scalar_one_or_none()
    except Exception as e:
        logger.error(f"获取用户信息失败: {str(e)}", exc_info=True)
        raise e

# 根据unionid获取用户信息（别名方法）
async def get_user_by_unionid(db: AsyncSession, unionid: str) -> Optional[User]:
    """根据unionid获取用户信息"""
    return await get_user_by_id(db, unionid)

# 更新用户能量（增量方式）
async def update_user_energy_delta(
    db: AsyncSession,
    user_id: str,
    energy_change: int,
    consumption_type: int = 0
) -> Optional[User]:
    """更新用户能量，支持增加或减少"""
    try:
        # 获取用户
        result = await db.execute(
            select(User).where(User.user_id == user_id).where(User.is_deleted == False)
        )
        user = result.scalar_one_or_none()
        
        if not user:
            logger.warning(f"用户 {user_id} 不存在")
            return None
        
        # 更新能量值
        new_energy = user.energy + energy_change
        if new_energy < 0:
            logger.warning(f"用户 {user_id} 能量不足，当前: {user.energy}, 尝试变更: {energy_change}")
            return None
        
        user.energy = new_energy
        await db.flush()
        await db.refresh(user)

        logger.info(f"用户 {user_id} 能量更新: {user.energy - energy_change} -> {user.energy}")
        return user
        
    except Exception as e:
        logger.error(f"更新用户能量失败: {str(e)}", exc_info=True)
        raise e

# 更新用户能量（绝对值方式）
async def update_user_energy(
    db: AsyncSession,
    user_id: str,
    new_energy: int,
    consumption_type: int = 1
) -> bool:
    """直接设置用户能量值"""
    try:
        # 获取用户
        result = await db.execute(
            select(User).where(User.user_id == user_id).where(User.is_deleted == False)
        )
        user = result.scalar_one_or_none()
        
        if not user:
            logger.warning(f"用户 {user_id} 不存在")
            return False
        
        # 检查能量值有效性
        if new_energy < 0:
            logger.warning(f"用户 {user_id} 设置的能量值无效: {new_energy}")
            return False
        
        old_energy = user.energy
        energy_change = new_energy - old_energy
        user.energy = new_energy
        await db.flush()
        

        logger.info(f"用户 {user_id} 能量直接设置: {old_energy} -> {new_energy}")
        return True
        
    except Exception as e:
        logger.error(f"设置用户能量失败: {str(e)}", exc_info=True)
        return False

# 检查用户能量是否足够
async def check_user_energy(
    db: AsyncSession,
    user_id: str,
    required_energy: int
) -> bool:
    """检查用户能量是否足够"""
    try:
        user = await get_user_by_id(db, user_id)
        if not user:
            return False
        
        return user.energy >= required_energy
        
    except Exception as e:
        logger.error(f"检查用户能量失败: {str(e)}", exc_info=True)
        return False

# 扣减用户能量
async def deduct_user_energy(
    db: AsyncSession,
    user_id: str,
    energy_cost: int
) -> bool:
    """扣减用户能量，返回是否成功"""
    try:
        # 检查能量是否足够
        if not await check_user_energy(db, user_id, energy_cost):
            return False
        
        # 扣减能量（传入消费类型：0-生成内容）
        user = await update_user_energy_delta(db, user_id, -energy_cost, 0)
        return user is not None
        
    except Exception as e:
        logger.error(f"扣减用户能量失败: {str(e)}", exc_info=True)
        return False 